package com.bilibili.juc.AtomicTest;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicMarkableReference;
// AtomicReference
// AtomicStampedReference
// AtomicMarkableReference
//

//    `AtomicReference` 可以带泛型（前面讲过）
//
// `AtomicReference<xxx> `*
//
//    `AtomicStampedReference` 带版本号以防CAS中的ABA问题（前面讲过）
//
// 携带版本号的引用类型原子类，可以解决ABA问题。解决修改过几次的问题。*
//
//    `AtomicMarkableReference`类似于上面的 ，但解决**一次性**问题
//
// 构造方法`AtomicMarkableReference(V initialRef, boolean initialMark)`
//
// 原子更新带有标记位的引用类型对象
//
// 解决是否修改过，它的定义就是将`状态戳`**简化**为`true|false`，类似一次性筷子

//来个案例
public class AtomicMarkableReferenceDemo {

    static AtomicMarkableReference markableReference = new AtomicMarkableReference(100,false);

    public static void main(String[] args) {
        new Thread(()->{
            boolean marked = markableReference.isMarked();
            System.out.println(Thread.currentThread().getName()+"\t"+"默认标识"+marked);
            //暂停1秒钟线程，等待后面的T2线程和我拿到一样的模式flag标识，都是false
            try {
                TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}
            markableReference.compareAndSet(100, 1000, marked, !marked);
        },"t1").start();

        new Thread(()->{
            boolean marked = markableReference.isMarked();
            System.out.println(Thread.currentThread().getName()+"\t"+"默认标识"+marked);
            //这里停2秒，让t1先修改,然后t2试着修改
            try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}
            boolean t2Result = markableReference.compareAndSet(100, 1000, marked, !marked);
            System.out.println(Thread.currentThread().getName()+"\t"+"t2线程result--"+t2Result);
            System.out.println(Thread.currentThread().getName()+"\t"+markableReference.isMarked());
            System.out.println(Thread.currentThread().getName()+"\t"+markableReference.getReference());

        },"t2").start();
    }
}

